using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace SharePointBrowser
{
    internal struct BlendFunction
    {
        public byte BlendOp;
        public byte BlendFlags;
        public byte SourceConstantAlpha;
        public byte AlphaFormat;
    }

    internal enum BlendOperation : byte
    {
        AC_SRC_OVER = 0x00
    }

    internal enum BlendFlags : byte
    {
        Zero = 0x00
    }

    internal enum SourceConstantAlpha : byte
    {
        Transparent = 0x00,
        Opaque = 0xFF
    }

    internal enum AlphaFormat : byte
    {
        AC_SRC_ALPHA = 0x01
    }

    internal static class DrawingHelper
    {
        #region PInvoke

        [DllImport("coredll.dll")]
        extern public static Int32 AlphaBlend(IntPtr hdcDest, Int32 xDest, Int32 yDest, Int32 cxDest, Int32 cyDest, IntPtr hdcSrc, Int32 xSrc, Int32 ySrc, Int32 cxSrc, Int32 cySrc, BlendFunction blendFunction);

        const int SRCCOPY = 0x00CC0020;

        [DllImport("coredll.dll")]
        public static extern int BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, uint dwRop);

        #endregion

        public static readonly Font LABEL_FONT = new Font(FontFamily.GenericSerif, 9F, FontStyle.Regular);
        public static readonly Font DESCRIPTION_FONT = new Font(FontFamily.GenericSerif, 7F, FontStyle.Regular);
        public static readonly Brush LABEL_BRUSH = new SolidBrush(Color.FromArgb(0x00, 0x33, 0x99));
        public static readonly Brush DESCRIPTION_BRUSH = new SolidBrush(Color.FromArgb(0x66, 0x66, 0x66));
        public static readonly Pen SEPARATOR_PEN = new Pen(Color.FromArgb(0x00, 0x33, 0x99));
        public static readonly Pen SEL_BORDER_PEN = new Pen(Color.FromArgb(0xD2, 0xB4, 0x7A));
        public static readonly Brush SEL_BRUSH = new SolidBrush(Color.FromArgb(0xFF, 0xE6, 0xA0));

        public static void DrawAlpha(Graphics graphics, Bitmap image, byte transparency, int x, int y)
        {
            using (Graphics gxSrc = Graphics.FromImage(image))
            {
                IntPtr hdcDst = graphics.GetHdc();
                IntPtr hdcSrc = gxSrc.GetHdc();
                BlendFunction blendFunction = new BlendFunction();
                blendFunction.BlendOp = (byte)BlendOperation.AC_SRC_OVER;   // Only supported blend operation
                blendFunction.BlendFlags = (byte)BlendFlags.Zero;           // Documentation says put 0 here
                blendFunction.SourceConstantAlpha = transparency;// Constant alpha factor
                blendFunction.AlphaFormat = (byte)0;                        // Don't look for per pixel alpha
                AlphaBlend(hdcDst, x, y, image.Width, image.Height, hdcSrc, 0, 0, image.Width, image.Height, blendFunction);
                graphics.ReleaseHdc(hdcDst);    // Required cleanup to GetHdc()
                gxSrc.ReleaseHdc(hdcSrc);       // Required cleanup to GetHdc()
            }
        }

        /// <summary>
        /// Gets the rectangle filled by the string
        /// </summary>
        public static Size GetStringRectangle(Form sender, string source, Font font)
        { 
            using (Graphics gx = sender.CreateGraphics())
            {
                try
                {
                    return new Size((int)gx.MeasureString(source, font).Width, (int)gx.MeasureString(source, font).Height);
                }
                catch
                {
                    return new Size(20, 20);
                }
            }
        }

        public static Bitmap ResizeBitmap(Bitmap bitmap, Size size)
        {
            if (bitmap.Width == size.Width && bitmap.Height == size.Height)
                return bitmap;

            Bitmap bitmapResized = new Bitmap(size.Width, size.Height);
            Graphics grPhoto = Graphics.FromImage(bitmapResized);
            grPhoto.DrawImage(bitmap,
                new Rectangle(0, 0, size.Width, size.Height),
                new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                GraphicsUnit.Pixel);
            grPhoto.Dispose();
            return bitmapResized;

        }

        public static int CloneImage(IntPtr hdcDest, int nWidth, int nHeight, IntPtr hdcSrc)
        {
            return BitBlt(hdcDest, 0, 0, nWidth, nHeight, hdcSrc, 0, 0, SRCCOPY);
        }

        public static string TrimText(string text, string elipsis, int width, Graphics graphics, Font font)
        {
            return graphics.MeasureString(text, font).Width <= width 
                ? text
                : TrimTextInt(text, width, 0, text.Length, graphics, font) + elipsis;
        }

        private static string TrimTextInt(string text, int width, int min, int max, Graphics graphics, Font font)
        {
            if (max - min <= 1)
            {
                return text.Substring(0, max);
            }
            else
            {
                int mid = (min + max) / 2;
                string midText = text.Substring(0, mid);
                SizeF size = graphics.MeasureString(midText, font);
                if ((int)size.Width == width)
                {
                    return midText;
                }
                else if (size.Width > width)
                {
                    return TrimTextInt(text, width, min, mid, graphics, font);
                }
                else
                {
                    return TrimTextInt(text, width, mid, max, graphics, font);
                }
            }
        }
    }
}